#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <functional>
#include <sys/wait.h>
#include "protocol.hpp"
#include <cassert>
#include<jsoncpp/json/json.h>


#define MYSELF 1

// 数据分割符号
#define SEP " "
#define SEP_LEN strlen(SEP)
// 行分隔符
#define LINE_SEP "\r\n"
// 行分隔符长度
#define LINE_SEP_LEN strlen(LINE_SEP)

namespace zxf
{

    bool complete_read(int sock, std::string &str, std::string &buf)
    {
        // tcp是面向字节流的
        // 我们发送的一条完整的请求应该是有两行的,第一行:data的长度,第二行是数据
        //"len_str" \r\n"data_str"\r\n
        //          |             |
        // 怎么保证能够读取完全呢,循环读取
        char buf_c[1024];
        while (true)
        {
            // 每次进来给buf_c 清0
            bzero(buf_c, 1024);
            ssize_t ret = recv(sock, (void *)buf_c, 1024, 0);
            if (ret > 0)
            {
                buf += buf_c;
                size_t pos1 = buf.find(LINE_SEP);
                if (pos1 == std::string::npos)
                {
                    // 没有找到
                    continue;
                }
                // 确定第一行读取完成
                int data_len = std::stoi(buf.substr(0, pos1));
                size_t pos2 = buf.find(LINE_SEP, pos1 + LINE_SEP_LEN);
                if (pos2 == std::string::npos)
                {
                    // 没有找到
                    continue;
                }
                if (pos1 < pos2 && pos1 + LINE_SEP_LEN + data_len == pos2)
                {
                    str += buf.substr(0, LINE_SEP_LEN + LINE_SEP_LEN + data_len + pos1);
                    buf.erase(0, LINE_SEP_LEN + LINE_SEP_LEN + data_len + pos1);
                    return true;
                }
            }
            else
            {
                std::cout << "断开链接/读取出错!!! exit !!" << std::endl;
                exit(1);
            }
        }
        return false;
    }

    // 添加报头
    std::string Headers(const std::string &str)
    {
        std::string ret = "";
        ret += std::to_string(str.size());
        ret += LINE_SEP;
        ret += str;
        ret += LINE_SEP;
        return ret;
    }

    // 去掉报头
    std::string enHeaders(const std::string &str)
    {
        // //"len_str" \r\n"data_str"\r\n
        // size_t pos1 = str.find(SEP_LEN);
        // size_t pos2 = str.rfind(SEP_LEN);
        // std::string ret = "";
        // std::cout<<ret<<std::endl;
        // ret = str.substr(pos1 + LINE_SEP_LEN, pos2 - pos1 - LINE_SEP_LEN);
        // return ret;
        std::string ret = "";
        auto pos = str.find(LINE_SEP);
        if (pos == std::string::npos)
            return ret;
        std::string text_len_string = str.substr(0, pos);
        int text_len = std::stoi(text_len_string);
        ret = str.substr(pos + LINE_SEP_LEN, text_len);
        return ret;
    }

    class request_data
    {
    public:
        request_data()
        {
        }
        request_data(int x, int y, char op) : _x(x), _y(y), _op(op)
        {
        }
        // 序列化 :  x,y,op -> "x op y"
        std::string serialize()
        {
#ifdef MYSELF
            std::string str;
            str += std::to_string(_x);
            str += SEP;
            str += _op;
            str += SEP;
            str += std::to_string(_y);
            return str;
#else
            Json::Value root; // 创建json对象
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;

            //
            std::string str;
            Json::FastWriter writer;
            str = writer.write(root);
            return str;
#endif
        }

        // 反序列化  "x op y" -> x,y,op
        bool reserialize(const std::string &str)
        {
#ifdef MYSELF
            size_t pos1 = str.find(SEP);
            size_t pos2 = str.rfind(SEP);
            if (pos1 != std::string::npos && pos2 != std::string::npos && pos1 != pos2)
            {
                _x = std::stoi(str.substr(0, pos1));
                _op = str[pos1 + SEP_LEN];
                _y = std::stoi(str.substr(pos2 + SEP_LEN));
            }
            else
            {
                std::cout << "reserialize_err,数据格式不对!!" << std::endl;
                return false;
            }
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);

            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
        }
        int _x;
        int _y;
        char _op;
    };

    class response_data
    {
    public:
        response_data() : _errCode(1), _result(0)
        {
        }
        response_data(int errCode, int result) : _errCode(errCode), _result(result)
        {
        }
        // 序列化
        std::string serialize()
        {

#ifdef MYSELF
            std::string str;
            str += std::to_string(_errCode);
            str += SEP;
            str += std::to_string(_result);
            return str;
#else
            Json::Value root; // 创建json对象
            root["errcode"] = _errCode;
            root["result"] = _result;

            //
            std::string str;
            Json::FastWriter writer;
            str = writer.write(root);
            return str;
#endif
        }

        // 反序列化
        bool reserialize(std::string &str)
        {

#ifdef MYSELF
            size_t pos1 = str.find(SEP);
            size_t pos2 = str.rfind(SEP);
            if (pos1 == pos2)
            {
                _errCode = std::stoi(str.substr(0, pos1));
                _result = std::stoi(str.substr(pos1 + SEP_LEN));
            }
            else
            {
                std::cout << "reserialize_err,数据格式不对!!" << std::endl;
                return false;
            }
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str,root);

            _errCode = root["errcode"].asInt();
            _result = root["result"].asInt();
#endif
        }

        int get_errCode()
        {
            return _errCode;
        }
        int get_result()
        {
            return _result;
        }

        void set_err(int errcode)
        {
            _errCode = errcode;
        }

        int _errCode;
        int _result;
    };
} // namespace zxf end!!